#include "pixel.h"
#include "node.h"
#include "cv.h"
#include "highgui.h"
#include <iostream>

/* This header contains the definition of the class pixel_array which is *
 * the data structure on which the our IFT implementation is based.      */

using namespace std;

class pixel_array{

private: 
	pixel * p_list;
	List<pixel> list1;
	double * input;
	int dim1 ;
	int dim2 ;
	int length ;

public:
	
	pixel_array(unsigned char * ii, int dd1, int dd2 , int * mouse_position, int press_time) {

		dim1 = dd1;
		dim2 = dd2;
		length = dim1 * dim2;

		input = new double[length];
        p_list = new pixel[length];

		memset(input , 0 , sizeof(double)*length);
   
		int i_s =0;
        double inf = 20000;
		Node<pixel> * P1;

	   for (int t= 0 ; t< press_time ; t++) {

		int temp_x = mouse_position[t*2 + 1];
		int temp_y = mouse_position[t*2 + 0];
			 input[temp_x * dim2 + temp_y] = -1;
		}

		for(int i_x = 0 ; i_x < dim1 ; i_x++){
			for (int i_y = 0 ; i_y < dim2  ; i_y++){

				//if( (i_x == mouse_position[1] && i_y == mouse_position[0]) ||
				//(i_x == mouse_position[3] && i_y == mouse_position[2])	)  input[i_x * dim2 + i_y] = -1;
				//else 
				if (input[i_x * dim2 + i_y] != -1) {
					input[i_x * dim2 + i_y] = double(ii[i_x * dim2 + i_y]);
				}

				p_list[i_s].set_intensity( input[i_x * dim2 + i_y]);
				p_list[i_s].set_x(i_x) ;
				p_list[i_s].set_y(i_y) ;

				if (input[i_x * dim2 + i_y] == -1) 	{
					p_list[i_s].set_h(0) ;
				    P1 = list1.CreatNode(p_list[i_s]);
			        list1.InsertFront(P1);
				    p_list[i_s].set_label(i_x * dim2 + i_y);
				}
				else {
					p_list[i_s].set_h(inf) ;
				    p_list[i_s].set_label(0);
			//		P1 = list1.CreatNode(p_list[i_s]);
			//		list1.InsertRear(P1);
				}

				i_s++;
			}
		}


	}

	~pixel_array(){

		delete [] input;
		delete [] p_list;
	}

int min_pixel(){

	    Node<pixel> * P1;
    	P1 = list1.DeleteFront();
		
		int p_x = P1->get_info().get_x();
		int p_y = P1->get_info().get_y();

		delete P1;
	    return p_x * dim2 + p_y;

}


void connection(int x , int y, int c_x , int c_y){

     if(x < 0 || y < 0 || x>dim1-1 || y>dim2-1) return;

	 int c = x * dim2 + y;
	 int co = c_x * dim2 + c_y;


	 if(p_list[c].get_i()<0) return;

	 double combine_value;

	 if(p_list[co].get_h() > input[c]) combine_value = p_list[co].get_h();
	 else combine_value = input[c];

	 if ( combine_value < p_list[c].get_h()) {
		 p_list[c].set_para(co);
		 p_list[c].set_h(combine_value);
		 p_list[c].set_label(p_list[co].get_label());
		 p_list[c].set_intensity(-1);
		 
		 Node <pixel> * P_c;
		 
		 //P_c = list1.Find(x,y);
         P_c = list1.CreatNode(p_list[c]);
		 P_c->set_info(combine_value);
		 //list1.DeleteNode(P_c);
		 list1.InsertOrder(P_c);

	 }
	 else return;
}

void print(){


		FILE * ofp = fopen("output.bin", "wb");

		int nn[2] = {dim2 , dim1};

	fwrite(nn , sizeof(int) , 2 , ofp);

		for(int i_x = 0 ; i_x < dim1 ; i_x++){
		for (int i_y = 0 ; i_y < dim2  ; i_y++){


			double temp[1] = {p_list[i_x * dim2 + i_y].get_label()};
            fwrite(temp , sizeof(double) , 1 , ofp);
		}
		}

		fclose(ofp);
}

bool  IslistEmpty(){
      
	return list1.isEmpty();

}

void result_show( IplImage* gray_image){

	for(int i_x = 1 ; i_x < dim1 - 1 ; i_x++){
		for (int i_y = 1 ; i_y < dim2 - 1  ; i_y++){

			if(p_list[i_x * dim2 + i_y].get_label() != p_list[i_x * dim2 + i_y + 1].get_label() ||
			p_list[i_x * dim2 + i_y].get_label() != p_list[i_x * dim2 + i_y - 1].get_label() ||
			p_list[i_x * dim2 + i_y].get_label() != p_list[(i_x+1) * dim2 + i_y + 1].get_label() ||
			p_list[i_x * dim2 + i_y].get_label() != p_list[(i_x-1) * dim2 + i_y + 1].get_label()){



			(gray_image->imageData + i_x * gray_image->widthStep)[i_y] = 255;

			}
		}
	}
}
	

};